﻿/*
 * Сделано в SharpDevelop.
 * Пользователь: max
 * Дата: 10.04.2012
 * Время: 22:16
 * 
 * Для изменения этого шаблона используйте Сервис | Настройка | Кодирование | Правка стандартных заголовков.
 */
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
using System.Collections.Generic;

namespace mxplay
{
	/// <summary>
	/// Description of ListEditorControl.
	/// </summary>
	public partial class ListEditorControl : UserControl
	{
		public ListEditorControl()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
			
			//
			// TODO: Add constructor code after the InitializeComponent() call.
			//
		}
		
		#region drag drop implementation
		private Size drag_size=SystemInformation.DragSize;
		private Rectangle drag_rectangle=Rectangle.Empty;
		private Point drag_point=Point.Empty;
		
		private void drag_mouse_down(MouseEventArgs e)
		{
			//обрабатываем только левую кнопку
			if(e.Button!= MouseButtons.Left) return;
			
			//запоминаем rectangle при выходе из которого
			//начинаем drag
			drag_rectangle=new Rectangle(e.X-drag_size.Width/2,e.Y-drag_size.Height/2,drag_size.Width,drag_size.Height);
			
			//и запоминаем точку начала операции
			drag_point=e.Location;
		}
		
		private void drag_mouse_up(MouseEventArgs e)
		{
			//обрабатываем только левую кнопку
			if(e.Button!= MouseButtons.Left) return;
			
			//сбрасываем
			drag_rectangle=Rectangle.Empty;
			drag_point=Point.Empty;
		}
		
		private void drag_mouse_move(MouseEventArgs e)
		{
			//обрабатываем только левую кнопку
			if(e.Button!= MouseButtons.Left) return;
			
			//если пусты - выходим
			if((drag_rectangle==Rectangle.Empty)||(drag_point==Point.Empty)) return;
			
			//смотрим на координату
			//если ещё в drag_rectangle
			//считаем что юзер просто так возюкает
			if(drag_rectangle.Contains(e.Location)) return;
			
			//мышь вышла за пределы drag_rectangle
			//юхер не прото так возюкает, а желает воспользоваться благами
			//граф. интерфейса
			//смотрим какой эелемент был по точкой начала перетаскивания
			int ind=drag_get_index_at_point(drag_point);
			if((ind<0)||(ind>=checkedListBox_internal.Items.Count)) return; //не было эдементов полд указателем
			
			//начинаем drag
			checkedListBox_internal.DoDragDrop(checkedListBox_internal.Items[ind], DragDropEffects.Move);
		}
		
		private object drag_get_item_at_point(Point pt)
		{
			int ind=drag_get_index_at_point(pt);
			if(ind>=0) return checkedListBox_internal.Items[ind];
			return null;
		}
		
		private int drag_get_index_at_point(Point pt)
		{
			int ret=-1;
			Rectangle exam_rect=Rectangle.Empty;
			for(int exam_index=0;exam_index<checkedListBox_internal.Items.Count;exam_index++)
			{
				exam_rect=checkedListBox_internal.GetItemRectangle(exam_index);
				if(exam_rect.Contains(pt))
				{
					ret=exam_index;
					break;
				}
			}
			return ret;
		}
		
		private void drag_drop(DragEventArgs e)
		{
			#if DEBUG
			Program.LogMessage(string.Format("Drag dropped event. Effect = {0}; Data = {1}",e.Effect,drag_get_formats(e.Data)));
			#endif
			
			if(e.Effect==DragDropEffects.None) return;
			
			if(e.Effect==DragDropEffects.Move)
			{
				//нам нужно знать индекс тащимого элемента - это есть в Data
				//и индекс эемента над которым бросили
				int ind_dragged=checkedListBox_internal.Items.IndexOf(e.Data.GetData(typeof(object)));
				int ind_dropped=drag_get_index_at_point(checkedListBox_internal.PointToClient(new Point(e.X,e.Y)));
				#if DEBUG
				Program.LogMessage(string.Format("Perform move item #{0} to #{1}",ind_dragged,ind_dropped));
				#endif
				ItemMove(ind_dragged,ind_dropped);
			}
		}
		
		private void drag_enter(DragEventArgs e)
		{
			object data_object=e.Data.GetData(typeof(object));
			//если тащимое - элемент из нашего листбокса
			//показываем move значок
			if(checkedListBox_internal.Items.Contains(data_object))
			{
				e.Effect= DragDropEffects.Move;
			}
			
			#if DEBUG
			Program.LogMessage(string.Format("Drag enter event. Effect = {0}; Data = {1}",e.Effect,drag_get_formats(e.Data)));
			#endif
		}
		
		private void drag_over(DragEventArgs e)
		{
			#if DEBUG
			Program.LogMessage(string.Format("Drag over event. Effect = {0}",e.Effect));
			#endif
			
			
		}
		
		private void drag_give_feedback(GiveFeedbackEventArgs e)
		{
			#if DEBUG
//			Program.LogMessage(string.Format("Drag give feedback event. Effect = {0}",e.Effect));
			#endif

//			e.UseDefaultCursors=true;
		}
		
		private void drag_query_continue(QueryContinueDragEventArgs e)
		{
			#if DEBUG
//			Program.LogMessage("Drag query continue drag event.");
			#endif
			
//			if(e.EscapePressed) e.Action=DragAction.Cancel;
			
			
		}
		
		private string drag_get_formats(IDataObject data)
		{
			if(data==null) return "null";
			
			string[] formats=data.GetFormats(true);
			System.Text.StringBuilder ret=new System.Text.StringBuilder();
			foreach(string one_format in formats)
			{
				ret.Append(one_format);
				ret.Append(";");
			}
			return ret.ToString();
		}
		#endregion
		
		public bool Changed
		{
			get; private set;
		}
		
		[Browsable(false)]
		public IEnumerable EnumAvailableItems
		{
			get
			{
				foreach(object item in checkedListBox_internal.Items)
				{
					yield return item;
				}
			}
			set
			{
				checkedListBox_internal.Items.Clear();
				foreach(object one_entry in value)
				{
					checkedListBox_internal.Items.Add(one_entry,false);
				}
				Changed=false;
			}
		}
		
		[Browsable(false)]
		public IEnumerable EnumCheckedItems
		{
			get
			{
				foreach(object one_item in checkedListBox_internal.CheckedItems)
				{
					yield return one_item;
				}
			}
			set
			{
				for(int i=0;i<checkedListBox_internal.Items.Count;i++)
				{
					checkedListBox_internal.SetItemChecked(i,false);
				}
				int cur_index=-1;
				foreach(object item in value)
				{
					cur_index=checkedListBox_internal.Items.IndexOf(item);
					if(cur_index>=0)
					{
						checkedListBox_internal.SetItemChecked(cur_index,true);
					}
				}
			}
		}
		
		public void ItemMoveUp()
		{
			int index_to_move=checkedListBox_internal.SelectedIndex;
			if(index_to_move<=0) return;
			
			object item_to_move=checkedListBox_internal.Items[index_to_move];
			CheckState check_state=checkedListBox_internal.GetItemCheckState(index_to_move);
			bool is_selected=checkedListBox_internal.SelectedIndex==index_to_move;
			
			checkedListBox_internal.Items.RemoveAt(index_to_move);
			int new_index=index_to_move-1;
			checkedListBox_internal.Items.Insert(new_index,item_to_move);
			checkedListBox_internal.SetItemCheckState(new_index, check_state);
			if(is_selected) checkedListBox_internal.SetSelected(new_index,true);
			
			Changed=true;
		}
		
		public void ItemMoveDown()
		{
			int index_to_move=checkedListBox_internal.SelectedIndex;
			if((index_to_move<0)||(index_to_move>=checkedListBox_internal.Items.Count-1)) return;
			
			object item_to_move=checkedListBox_internal.Items[index_to_move];
			CheckState check_state=checkedListBox_internal.GetItemCheckState(index_to_move);
			bool is_selected=checkedListBox_internal.SelectedIndex==index_to_move;
			
			checkedListBox_internal.Items.RemoveAt(index_to_move);
			int new_index=index_to_move+1;
			checkedListBox_internal.Items.Insert(new_index,item_to_move);
			checkedListBox_internal.SetItemCheckState(new_index,check_state);
			if(is_selected) checkedListBox_internal.SetSelected(new_index,true);
			Changed=true;
		}
		
		public void ItemMove(int index_to_move,int new_index)
		{
			if(index_to_move<0) return;
			if(index_to_move>=checkedListBox_internal.Items.Count) return;
			if(new_index<0) return;
			if(new_index>=checkedListBox_internal.Items.Count) return;
			if(index_to_move==new_index) return;
			
			object item_to_move=checkedListBox_internal.Items[index_to_move];
			CheckState check_state=checkedListBox_internal.GetItemCheckState(index_to_move);
			bool is_selected=checkedListBox_internal.SelectedIndex==index_to_move;
			
			checkedListBox_internal.Items.RemoveAt(index_to_move);
			checkedListBox_internal.Items.Insert(new_index,item_to_move);
			checkedListBox_internal.SetItemCheckState(new_index,check_state);
			if(is_selected) checkedListBox_internal.SetSelected(new_index,true);
			
			Changed=true;
		}
		
		void ButtonUpClick(object sender, EventArgs e)
		{
			ItemMoveUp();
		}
		
		void ButtonDownClick(object sender, EventArgs e)
		{
			ItemMoveDown();
		}
		
		void CheckedListBox_internalItemCheck(object sender, ItemCheckEventArgs e)
		{
			Changed=true;
		}
		
		void CheckedListBox_internalMouseDown(object sender, MouseEventArgs e)
		{
			drag_mouse_down(e);
		}
		
		void CheckedListBox_internalMouseUp(object sender, MouseEventArgs e)
		{
			drag_mouse_up(e);
		}
		
		void CheckedListBox_internalMouseMove(object sender, MouseEventArgs e)
		{
			drag_mouse_move(e);
		}
		
		void CheckedListBox_internalDragDrop(object sender, DragEventArgs e)
		{
			drag_drop(e);
		}
		
		void CheckedListBox_internalDragEnter(object sender, DragEventArgs e)
		{
			drag_enter(e);
		}
		
		void CheckedListBox_internalDragOver(object sender, DragEventArgs e)
		{
			drag_over(e);
		}
		
		void CheckedListBox_internalGiveFeedback(object sender, GiveFeedbackEventArgs e)
		{
			drag_give_feedback(e);
		}
		
		void CheckedListBox_internalQueryContinueDrag(object sender, QueryContinueDragEventArgs e)
		{
			drag_query_continue(e);
		}
	}
}
